package parser.util;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import parser.astgen.NodeFactory;
import parser.astlib.OclActualParameterListItem;
import parser.astlib.OclFormalParameter;
import parser.sablecc.analysis.AttrEvalException;
import uml2.kernel.Type;
import uml2.ocl2.Variable;

public class Transformations {
        
	private NodeFactory factory = null;
	private Type defaultVarType = null;
        
	public Transformations(NodeFactory factory) {
		this.factory = factory;
	}
        
	public void setDefaultType(Type t) {
        defaultVarType = t;
    }

    /**
     * Transforms list of OclActualParameterListItem instances into a list of 
     * Variable for iterator variables and checks that all
     * instances of the input list indeed have a variable type set.
     *
     * Input: List of OclActualParameterListItem instances. <br>
     * Output: List of Variable instances with type field set to
     *      default variable type if no type specified.
     */
	public List transform(List param) throws AttrEvalException {
		List result = new LinkedList();
		Iterator it = param.iterator();
		
		while ( it.hasNext() ) {
			Object obj = it.next();
			
			// Input list's elements must be instances of OclActualParameterListItem
			if (!(obj instanceof OclActualParameterListItem))
				throw new AttrEvalException("Expecting objects of type OclActualParameterListItem but found " + obj.getClass().getName());
			
			OclActualParameterListItem item = (OclActualParameterListItem) obj;
			
			boolean isFormalParameter = item.isFormalParameter();
			boolean isSimpleName = item.isSimpleName();
			boolean isValid = (isFormalParameter | isSimpleName );
			
			if (! isValid)
				throw new AttrEvalException("Iterator variables must not have an initial value");
			if ( defaultVarType == null )
				throw new AttrEvalException("Default variable type must be set for iterator variable transformation");
			
			Variable v = (Variable) factory.createNode("Variable");
			// CASE 1. Formal Parameter
			if ( isFormalParameter ) {
				OclFormalParameter fp = item.getFormalParameterValue();
				v.setName(fp.getName());
				Type type = fp.getType();
				if ( type == null ) {
					throw new AttrEvalException("'type' of a formal parameter must be defined, but is not for iterator variable '" +
							fp.getName() +"'");
				}
				v.setType(type);
			// CASE 2. Simple Name
			} else if ( isSimpleName ) {
				String name = item.getSimpleNameValue();
				v.setName(name);
				v.setType(defaultVarType);
			}
			result.add(v);
		}
		defaultVarType = null;
		return result;
	}
}
